/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import javax.sip.InvalidArgumentException;
import javax.sip.header.AcceptHeader;
import java.text.ParseException;

/**
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class AcceptHeaderImpl extends ParametrizedHeaderBase implements AcceptHeader {
    /**
     * Content type value.
     */
    private String contentType;
    /**
     * Content subtype value.
     */
    private String contentSubType;
    /**
     * Indicates that the header allows all content media types, that is the content type is "*".
     */
    private boolean allowsAllContentTypes;
    /**
     * Indicates that the header allows all content media subtypes, that is the content subtype is "*".
     */
    private boolean allowsAllContentSubTypes;

    private static final AcceptHeaderParser parser = new AcceptHeaderParser();

    protected HeaderParser getParser() {
        return parser;
    }

    public AcceptHeaderImpl() {
        super(AcceptHeader.NAME);
    }

    AcceptHeaderImpl(byte[] data, int start, int end) {
        super(AcceptHeader.NAME, data, start, end);
    }

    public Object clone() {
        final AcceptHeaderImpl header = new AcceptHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.cloneParameters(this);
            header.contentType = this.contentType;
            header.contentSubType = this.contentSubType;
            header.allowsAllContentSubTypes = this.allowsAllContentSubTypes;
            header.allowsAllContentTypes = this.allowsAllContentTypes;
        }
        return header;
    }

    /**
     * Sets q-value for media-range in AcceptHeader. Q-values allow the user to
     * indicate the relative degree of preference for that media-range, using
     * the qvalue scale from 0 to 1. If no q-value is present, the media-range
     * should be treated as having a q-value of 1.
     *
     * @param qValue the new float value of the q-value, a value of -1 resets
     *               the qValue.
     * @throws InvalidArgumentException if the q parameter value is not
     *                                  <code>-1</code> or between <code>0 and 1</code>.
     */
    public void setQValue(float qValue) throws InvalidArgumentException {
        try {
            setParameter("q", Float.toString(qValue));
        } catch (ParseException e) {
            throw new InvalidArgumentException("Cannot set the q-value!", e);
        }
    }

    /**
     * Gets q-value of media-range in AcceptHeader. A value of <code>-1</code>
     * indicates the<code>q-value</code> is not set.
     *
     * @return q-value of media-range, -1 if q-value is not set.
     */
    public float getQValue() {
        String qValue = getParameter("q");
        if (qValue != null)
            return Float.parseFloat(qValue);
        else
            return -1.0f;
    }

    /**
     * Gets boolean value to indicate if the AcceptHeader allows all media
     * sub-types, that is the content sub-type is "*".
     *
     * @return true if all content sub-types are allowed, false otherwise.
     */
    public boolean allowsAllContentSubTypes() {
        parse();
        return allowsAllContentSubTypes;
    }

    /**
     * Gets boolean value to indicate if the AcceptHeader allows all media
     * types, that is the content type is "*".
     *
     * @return <code>true</code> if all content types are allowed, <code>false</code> otherwise.
     */
    public boolean allowsAllContentTypes() {
        parse();
        return allowsAllContentTypes;
    }

    /**
     * Sets value of media type of Header with Content Type.
     *
     * @param contentType the new string value of the content type.
     * @throws ParseException which signals that an error has been reached
     *                        unexpectedly while parsing the contentType value.
     */
    public void setContentType(String contentType) throws ParseException {
        parse();
        this.contentType = contentType;
        allowsAllContentTypes = contentType.equals("*");
        invalidateHeaderData();
    }

    /**
     * Gets media type of Header with Content type.
     *
     * @return media type of Header with Content type.
     */
    public String getContentType() {
        parse();
        return contentType;
    }

    /**
     * Sets value of media subtype of Header with Content sub-type.
     *
     * @param contentSubType the new string value of the content sub-type.
     * @throws ParseException which signals that an error has been reached
     *                        unexpectedly while parsing the contentSubType value.
     */
    public void setContentSubType(String contentSubType) throws ParseException {
        parse();
        this.contentSubType = contentSubType;
        allowsAllContentSubTypes = contentSubType.equals("*");
        invalidateHeaderData();
    }

    /**
     * Gets media sub-type of Header with Content sub-type.
     *
     * @return media sub-type of Header with Content sub-type.
     */
    public String getContentSubType() {
        parse();
        return contentSubType;
    }

    /**
     * Returns string representation of the header's value.
     *
     * @return The string representation of the header's value.
     */
    protected String getValueAsString() {
        return contentType + "/" + contentSubType;
    }
}
/*
 * $Log$
 */